package framework.collision;

import java.awt.geom.Rectangle2D;
import java.io.IOException;
import java.util.ArrayList;

import org.newdawn.slick.Animation;
import org.newdawn.slick.GameContainer;
import org.newdawn.slick.Graphics;
import org.newdawn.slick.Image;
import org.newdawn.slick.SlickException;
import org.newdawn.slick.geom.Point;
import org.newdawn.slick.particles.ConfigurableEmitter;
import org.newdawn.slick.particles.ParticleIO;
import org.newdawn.slick.particles.ParticleSystem;

import attack.nartan.FireBall;
import framework.BasicFighter;
import framework.NartanAnimationManager;
import framework.Util;
import framework.attack.BasicAttack;

public class SimpleAttackCollisionManager implements AttackCollisionManager {

	private ArrayList<BasicFighter> fighters;

	private ArrayList<BasicAttack<?>> attacks;

	private final static int TIME_BLOOD = 500;

	private ArrayList<Hit> hits;

	private Animation impact;

	private Point p;

	private ParticleSystem system;

	private int timeBlood1;

	private int timeBlood2;

	private ConfigurableEmitter blood;
	
	//private ConfigurableEmitter blood2;

	public SimpleAttackCollisionManager() {
		fighters = new ArrayList<>();
		attacks = new ArrayList<>();
		hits = new ArrayList<>();
		Image frame = new NartanAnimationManager().getSpriteSheet().getSprite(1, 4); 
		Animation impact = new Animation();
		impact.addFrame(frame, 50);
		impact.setLooping(false);
		this.impact = impact;
		p = null;
		blood = null;
		timeBlood1 = timeBlood2 = 0;
		try {
			system = new ParticleSystem(new Image("/resources/blood_particle.png"), 100);
			blood = ParticleIO.loadEmitter("resources/blood.xml");
			blood.setEnabled(false);
			system.addEmitter(blood);
		} catch (SlickException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	@Override
	public void addFighter(BasicFighter f) {
		fighters.add(f);
	}

	@Override
	public void addAttack(BasicAttack<?> a) {
		attacks.add(a);
	}

	@Override
	public void removeAttack(BasicAttack<?> a) {
		//attacks.remove(a);
	}

	public void clean() {
		for(int i = 0; i < attacks.size(); i++) {
			if(!attacks.get(i).isActive()) {
				attacks.remove(i);
			}
		}
	}

	public void draw(Graphics g) {
		if (p != null && !impact.isStopped()) {
			impact.draw(p.getX() - impact.getWidth() * 0.75f, p.getY() - impact.getHeight() * 0.75f, impact.getWidth() * 1.5f, impact.getHeight() * 1.5f);
		}
		system.render();
	}

	@Override
	public void update(GameContainer gc, int delta) {
		Rectangle2D collision;
		hits = new ArrayList<>();
		ArrayList<BasicAttack<?>> att = new ArrayList<>();
		ArrayList<Rectangle2D> rect = new ArrayList<>();
		if (timeBlood1 > TIME_BLOOD) {
			blood.setEnabled(false);
		}
		if (timeBlood2 > TIME_BLOOD) {
			//blood2.setEnabled(false);
		}

		for(BasicAttack<?> a : this.attacks) {
			for(BasicFighter f : this.fighters) {
				if(a.getHitBox() != null && a.getHitBox().intersects(f.getHitBox()) && f != a.getAttacker() && a.isActive()) {
					collision = Util.getCollision(a, f);
					hits.add(new Hit(a, f, collision));
				}
			}
			for(BasicAttack<?> a2 : this.attacks) {
				if(a.getHitBox() != null  && a2.getHitBox() != null && a.collidesOnAttack() && a2.collidesOnAttack() && 
				   a.getHitBox().intersects(a2.getHitBox()) && a != a2 && a.isActive()) {
					att.add(a);
					att.add(a2);
					rect.add(Util.getCollision(a, a2));
				}
			}
		}

		system.update(delta);
		
		for(Hit hit : hits) {
			hit.getFrom().onHit(hit.getTo(), hit.getCollision());
			if (timeBlood1 == 0 || timeBlood1 > TIME_BLOOD) {
				blood.setPosition((float) hit.getTo().getHitBox().getCenterX(), (float) hit.getTo().getHitBox().getCenterY());
				//blood.replay();
				blood.setEnabled(true);
				timeBlood1 = 1;
			}
		}
		
		for(BasicAttack<?> coll : att) {
			coll.interrupt();
		}
		
		for(Rectangle2D r : rect) {
			p = new Point((float) r.getCenterX(), (float) r.getCenterY());
			impact.restart();
		}
		
		if (timeBlood1 > 0 && timeBlood1 <= TIME_BLOOD) {
			timeBlood1 += delta;
		}
		
		timeBlood2 += delta;
		
		clean();
	}

	public class Hit {

		private Rectangle2D collision;

		private BasicAttack<?> from;

		private BasicFighter to;

		public Hit(BasicAttack<?> from, BasicFighter to, Rectangle2D collision) {
			this.collision = collision;
			this.from = from;
			this.to = to;
		}

		public Rectangle2D getCollision() {
			return collision;
		}

		public void setCollision(Rectangle2D collision) {
			this.collision = collision;
		}

		public BasicAttack<?> getFrom() {
			return from;
		}

		public void setFrom(BasicAttack<?> from) {
			this.from = from;
		}

		public BasicFighter getTo() {
			return to;
		}

		public void setTo(BasicFighter to) {
			this.to = to;
		}
	}
}